class Protocol(object):
    fcstab = [
        0, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5,
        0xe97e, 0xf8f7, 0x1081, 0x108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb,
        0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
        0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x318, 0x77a7,
        0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d,
        0x6116, 0x709f, 0x420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a,
        0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56,
        0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x630, 0x17b9, 0xef4e,
        0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a,
        0x16b1, 0x738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a,
        0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
        0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x948, 0x3bd3, 0x2a5a, 0x5ee5,
        0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb,
        0xa50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd,
        0xc134, 0x39c3, 0x284a, 0x1ad1, 0xb58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497,
        0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0xc60, 0x1de9, 0x2f72, 0x3efb, 0xd68d,
        0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0xd68,
        0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854,
        0x59dd, 0x2d62, 0x3ceb, 0xe70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
        0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0xf78]

    PPPINITFCS16 = 0xffff
    PPPGOODFCS16 = 0xf0b8

    def __init__(self):
        self.__index = 1
        self.__address = None  # 地址
        self.__address_type = None  # 地址类型
        self.__logi_address = None  # 逻辑地址
        self.__extension_address = None  # 扩展地址
        self._link_user_data = None  # 链路用户数据
        pass

    def set_address(self, address):
        self.__address = address
        return self

    def set_address_type(self, address_type):
        self.__address_type = address_type
        return self

    def set_logi_add(self, logi_address):
        self.__logi_address = logi_address
        return self

    def set_link_user_data(self, link_user_data):
        self._link_user_data = link_user_data
        return self

    def get_address(self):
        return self.__address

    def set_extension_address(self, extension_address):
        self.__extension_address = extension_address
        return self

    def get_extension_address(self):
        return self.__extension_address

    def get_address_type(self):
        return self.__address_type

    def get_logi_add(self):
        return self.__logi_address

    def get_link_user_data(self):
        return self._link_user_data

    """"
    格式化698帧
    """

    def format_frame_string(self) -> str:
        bytes = bytearray()
        bytes1 = bytearray()

        # 添加起始字符和长度域
        bytes.append(0x68)
        frame_length = b'\x00\x00'
        bytes.extend(frame_length)
        bytes1.extend(frame_length)

        # 添加控制域
        bytes.append(0x43)
        bytes1.append(0x43)
        if not self.__address:
            server_address = bytearray(b'\xaa\xaa\xaa\xaa\xaa\xaa')
            self.__address = self.__byte_to_hex_string(server_address)
        else:
            # reversed_server_address = server_address[::-1]

            server_address = byte_array = bytearray(
                [int(self.__address[i:i + 2], 16) for i in range(0, len(self.__address), 2)])
            # reversed_server_address = server_address[::-1]
        address_type_integer = int(self.__address_type, 16) << 6
        address_len_integer = int("05", 16)
        address_logi_integer = int("00", 16) << 4
        extension_address = bytearray()
        if self.__extension_address:
            address_len_integer = int("06", 16)
            address_logi_integer = int(self.__logi_address, 16) << 4
            extension_address = byte_array = bytearray(
                [int(self.__extension_address[i:i + 2], 16) for i in range(0, len(self.__extension_address), 2)])
        address_integer = address_type_integer | address_logi_integer | address_len_integer
        address_high = bytearray.fromhex('0x{:02x}'.format(address_integer)[2:])
        bytes.extend(address_high)
        bytes1.extend(address_high)
        if self.__extension_address:
            bytes.extend(extension_address)
            bytes1.extend(extension_address)
        bytes.extend(server_address)
        bytes1.extend(server_address)

        if self.__index == 1:
            client_address = bytearray(b'\x10')
            self.__index += 1
        else:
            client_address = bytearray(b'\x09')
        bytes.append(client_address[0])
        bytes1.append(client_address[0])
        bytes3 = bytearray(bytes1)

        # 添加校验码计算HCS的数组
        bytes2 = bytearray(bytes)
        bytes2.extend([0x00, 0x00])
        # 添加APDU数据
        new_bytes_data = bytearray.fromhex(self._link_user_data.replace(' ', ''))
        bytes2.extend(new_bytes_data)
        bytes2.extend([0x00, 0x00])
        bytes2.append(0x16)
        # 计算长度域的值
        frame_length_field = len(bytes2) - 2
        frame_length_bytes = frame_length_field.to_bytes(2, byteorder='little')
        bytes[1] = frame_length_bytes[0]
        bytes[2] = frame_length_bytes[1]
        bytes1[0] = frame_length_bytes[0]
        bytes1[1] = frame_length_bytes[1]
        bytes3[0] = frame_length_bytes[0]
        bytes3[1] = frame_length_bytes[1]

        # 计算HCS和FCS
        bytes1.extend([0x00, 0x00])
        checksum = self.__compute_fcs16(bytes1, len(bytes1) - 2)
        checksum_bytes = [int(checksum[i:i + 2], 16) for i in range(0, len(checksum), 2)]
        bytes.extend(checksum_bytes)

        bytes.extend(new_bytes_data)
        bytes3.extend(checksum_bytes)
        bytes3.extend(new_bytes_data)
        bytes3.extend([0x00, 0x00])
        checksum1 = self.__compute_fcs16(bytes3, len(bytes3) - 2)
        checksum_bytes1 = [int(checksum1[i:i + 2], 16) for i in range(0, len(checksum1), 2)]
        bytes.extend(checksum_bytes1)
        bytes.extend([0x16])

        result = self.__bytes_to_string(bytes)

        return result

    def generate_frame_not68H(self, type, start):
        result = None
        bytes = bytearray()
        bytes1 = bytearray()

        # 添加起始字符和长度域
        bytes.append(0x68)
        frame_length = b'\x00\x00'
        bytes.extend(frame_length)
        bytes1.extend(frame_length)

        # 添加控制域
        if type==18:
            bytes.append(0x4b)
            bytes1.append(0x4b)
        else:
            bytes.append(0x43)
            bytes1.append(0x43)
        if not self.__address:
            server_address = bytearray(b'\xaa\xaa\xaa\xaa\xaa\xaa')
            self.__address = self.__byte_to_hex_string(server_address)
        else:
            # reversed_server_address = server_address[::-1]

            server_address = byte_array = bytearray(
                [int(self.__address[i:i + 2], 16) for i in range(0, len(self.__address), 2)])
            # reversed_server_address = server_address[::-1]
        address_type_integer = int(self.__address_type, 16) << 6
        address_len_integer = int("05", 16)
        address_logi_integer = int("00", 16) << 4
        extension_address = bytearray()
        if self.__extension_address:
            address_len_integer = int("06", 16)
            address_logi_integer = int(self.__logi_address, 16) << 4
            extension_address = byte_array = bytearray(
                [int(self.__extension_address[i:i + 2], 16) for i in range(0, len(self.__extension_address), 2)])
        address_integer = address_type_integer | address_logi_integer | address_len_integer
        print(hex(address_integer))
        address_high = bytearray.fromhex('0x{:02x}'.format(address_integer)[2:])
        print(address_high)
        bytes.extend(address_high)
        bytes1.extend(address_high)
        if self.__extension_address:
            bytes.extend(extension_address)
            bytes1.extend(extension_address)
        bytes.extend(server_address)
        bytes1.extend(server_address)

        if self.__index == 1:
            client_address = bytearray(b'\x10')
            self.__index += 1
        else:
            client_address = bytearray(b'\x09')
        bytes.append(client_address[0])
        bytes1.append(client_address[0])
        bytes3 = bytearray(bytes1)

        # 添加校验码计算HCS的数组
        bytes2 = bytearray(bytes)
        bytes2.extend([0x00, 0x00])
        # 添加APDU数据
        new_bytes_data = bytearray.fromhex(self._link_user_data.replace(' ', ''))
        bytes2.extend(new_bytes_data)
        bytes2.extend([0x00, 0x00])
        bytes2.append(0x16)
        # 计算长度域的值
        frame_length_field = len(bytes2) - 2
        frame_length_bytes = frame_length_field.to_bytes(2, byteorder='little')
        bytes[1] = frame_length_bytes[0]
        bytes[2] = frame_length_bytes[1]
        bytes1[0] = frame_length_bytes[0]
        bytes1[1] = frame_length_bytes[1]
        bytes3[0] = frame_length_bytes[0]
        bytes3[1] = frame_length_bytes[1]

        # 计算HCS和FCS
        bytes1.extend([0x00, 0x00])
        checksum = self.__compute_fcs16(bytes1, len(bytes1) - 2)
        checksum_bytes = [int(checksum[i:i + 2], 16) for i in range(0, len(checksum), 2)]
        bytes.extend(checksum_bytes)

        bytes.extend(new_bytes_data)
        bytes3.extend(checksum_bytes)
        bytes3.extend(new_bytes_data)
        bytes3.extend([0x00, 0x00])
        checksum1 = self.__compute_fcs16(bytes3, len(bytes3) - 2)
        checksum_bytes1 = [int(checksum1[i:i + 2], 16) for i in range(0, len(checksum1), 2)]
        bytes.extend(checksum_bytes1)
        bytes.extend([0x16])

        if type == 1:
            new_bytes = bytearray()
            new_bytes.append(start)
            new_bytes.extend(bytes)
            new_bytes[0] = start
            result = self.__bytes_to_string(new_bytes)

        if type == 2:
            new_bytes = bytearray()
            new_bytes.append(start)
            new_bytes.extend(bytes)
            result = self.__bytes_to_string(new_bytes)
        if type == 3:
            new_bytes = bytearray()
            new_bytes.append(start)
            new_bytes.append(start)
            new_bytes.extend(bytes)
            result = self.__bytes_to_string(new_bytes)
        if type == 4:
            new_bytes = bytearray()
            new_bytes.append(start)
            new_bytes.extend(bytes)
            result = self.__bytes_to_string(new_bytes)
        if type == 5:
            new_bytes = bytearray()
            new_bytes.append(start)
            new_bytes.append(start)
            new_bytes.extend(bytes)
            result = self.__bytes_to_string(new_bytes)
        if type == 6:
            new_bytes = bytearray()
            new_bytes.extend(bytes)
            new_bytes[1] = new_bytes[1] - 0x03
            result = self.__bytes_to_string(new_bytes)
        if type == 7:
            new_bytes = bytearray()
            new_bytes.extend(bytes)
            new_bytes[1] = new_bytes[1] + 2
            result = self.__bytes_to_string(new_bytes)
        if type == 8:
            new_bytes = bytearray()
            new_bytes.extend(bytes)
            new_bytes[1] =0xff
            new_bytes[2] =0xff
            result = self.__bytes_to_string(new_bytes)
        if type == 9:
            new_bytes = bytearray()
            new_bytes.extend(bytes)
            new_bytes[3] = 0x31
        if type == 10:
            new_bytes = bytearray()
            new_bytes.extend(bytes)
            new_bytes[3] = 0x03

            result = self.__bytes_to_string(new_bytes)
        if type == 11:
            new_bytes = bytearray()
            new_bytes.extend(bytes)
            new_bytes[3] = 0x2a
            result = self.__bytes_to_string(new_bytes)
        if type == 12:
            new_bytes = bytearray()
            new_bytes.extend(bytes)
            new_bytes[12] = new_bytes[12] + 0x01
            result = self.__bytes_to_string(new_bytes)
        if type == 13:
            new_bytes = bytearray()
            new_bytes.extend(bytes)
            new_bytes[23] = new_bytes[23] + 0x01
            result = self.__bytes_to_string(new_bytes)
        if type == 14:
            new_bytes = bytearray()
            new_bytes.extend(bytes)
            new_bytes[24] = new_bytes[24] + 0x01
            result = self.__bytes_to_string(new_bytes)
        if type == 15:
            new_bytes = bytearray()
            new_bytes.extend(bytes)
            result = self.__bytes_to_string(new_bytes)

        if type == 16:
            new_bytes = bytearray()
            new_bytes.append(0xfe)
            new_bytes.append(0xfe)
            new_bytes.append(0xfe)
            new_bytes.append(0xfe)
            new_bytes.extend(bytes)
            result = self.__bytes_to_string(new_bytes)
        if type == 17:
            new_bytes = bytearray()
            new_bytes.extend(bytes)
            result = self.__bytes_to_string(new_bytes)
        if type == 18:
            new_bytes = bytearray()
            new_bytes.extend(bytes)
            result = self.__bytes_to_string(new_bytes)
        return result
    """
    解析698响应帧：目前只能将698帧中的APDU解析出来
    """

    def parser_frame(self, response: str):
        index = response.index("68")
        if index == -1:
            return None
        whole_frame = response[index:]
        address_features = whole_frame[8:10]
        address_features_bin = self.__hex2bin(address_features)
        address_type = self.__bin2hex(address_features_bin[0:2])
        self.set_address_type(address_type)
        address_logic = self.__bin2hex(address_features_bin[2:4])
        self.set_logi_add(address_logic)
        address_len = self.__bin2hex(address_features_bin[4:8])
        address_len_integer = int(address_len, 16)

        if address_len_integer == 6:
            address_extension = whole_frame[10:12]
            self.set_extension_address(address_extension)
        self.set_address(whole_frame[10:10 + address_len_integer * 2])
        link_user_data_index = (
                                           5 + address_len_integer + 1 + 3) * 2  # 1字节起始符+2字节长度域字节数+1字节控制码+1字节地址特征+地址长度+1字节客户机地址+2字节帧头校验
        self.set_link_user_data(whole_frame[link_user_data_index:len(whole_frame) - 6])
        return self

    def __byte_to_hex(self, byte):
        int_val = byte if isinstance(byte, int) else byte[0]
        hex_val = format(int_val, '02X')
        return hex_val

    def __byte_to_hex_string(self, byte_array):
        result = ""
        if byte_array is not None:
            result = self.__byte_to_hex_string_range(byte_array, 0, len(byte_array))
        return result

    def __byte_to_hex_string_range(self, byte_array, start: int, end: int):
        result = ""
        for i in range(start, end):
            byte_val = byte_array[i]
            int_val = byte_val if isinstance(byte_val, int) else byte_val[0]
            hex_val = format(int_val, '02X')
            result += hex_val
        return result

    def __bcd_to_int(self, bcd):
        i_val = bcd & 0xF
        i_val += ((bcd >> 4) & 0xF) * 10
        return i_val

    def __bytes_to_string(self, byte_array):
        return byte_array.hex()

    def __compute_fcs16(self, data: bytes, len: int) -> str:
        trialfcs = self.__pppfcs16(self.PPPINITFCS16, data, len)
        trialfcs ^= 0xffff
        data[len] = trialfcs & 0xff
        data[len + 1] = (trialfcs >> 8) & 0xff

        c = [(trialfcs & 0xff)]
        c1 = [(trialfcs >> 8) & 0xff]

        trialfcs = self.__pppfcs16(self.PPPINITFCS16, data, len + 2)
        if trialfcs == self.PPPGOODFCS16:
            return ''.join(format(x, '02x') for x in c[::-1] + c1[::-1])  # Reversed order for little endian
        return None

    def __pppfcs16(self, fcs, cp, length):
        for index in range(length):
            fcs = (fcs >> 8) ^ self.fcstab[(fcs ^ cp[index]) & 0xff]
        return fcs

    def __bin2hex(self, bin_str):
        bin_int = int(bin_str, 2)
        # 将整数转换为十六进制字符串
        hex_str = format(bin_int, '02x')
        return hex_str

    def __hex2bin(self, hex_str):
        hex_int = int(hex_str, 16)
        # 将整数转换为二进制字符串，并补齐到8位
        bin_str = format(hex_int, '08b')
        return bin_str


#
# if __name__ == '__main__':
#     protocol = Protocol()
#     protocol.set_extension_address("02")
#     protocol.set_logi_add("02")
#     protocol.set_address("000000000000")
#     protocol.set_address_type("00")
#     protocol.set_link_user_data("0501004012020000")
#     ss = protocol.format_frame_string()
#     print(ss)
#     protocol.parser_frame(ss)
#     print(protocol.get_extension_address())
#     print(protocol.get_address())
#     print(protocol.get_link_user_data())

# if __name__ == "__main__":
#     hex_int = int("898", 16)
#     print(hex_int)
#     # 将整数转换为二进制字符串，并补齐到8位
#     bin_str = format(hex_int, '08b')
#     ii = int(bin_str, 2)
#     print(ii)
